package sysDao

import (
	"context"
	"fmt"
	"gitee.com/jokces/kit/enum"
	"gitee.com/jokces/kit/errc"
	sysModel "gitee.com/jokces/kit/global/admin/model"
	"gitee.com/jokces/kit/typ"
)

func (d *Dao) InsertFile(ctx context.Context, in sysModel.SysFileRecord) error {
	row, err := d.dao.Context(ctx).InsertOne(in)
	if err != nil {
		return errc.WithStack(err)
	}
	if row <= 0 {
		return errc.ErrInternalErr.MultiMsg("add file error")
	}
	return nil
}
func (d *Dao) GetFile(ctx context.Context, fileName string) (bool, sysModel.SysFileRecord, error) {
	rs := sysModel.SysFileRecord{}
	exist, err := d.dao.Context(ctx).Where("file_name = ?", fileName).Get(&rs)
	if err != nil {
		return false, rs, errc.WithStack(err)
	}
	return exist, rs, nil
}

func (d *Dao) ParamGetOne(ctx context.Context, req *sysModel.SysParam) (bool, *sysModel.SysParam, error) {
	rs := &sysModel.SysParam{}
	sess := d.dao.Context(ctx)
	if req.Id > 0 {
		sess.And("id = ?", req.Id)
	}
	if req.Key != "" {
		sess.And("`key` = ?", req.Key)
	}
	if req.Status > 0 {
		sess.And("`status` = ?", req.Status)
	}
	exist, err := sess.Get(rs)
	return exist, rs, errc.WithStack(err)
}
func (d *Dao) ParamToObject(ctx context.Context, key string, out interface{}) (bool, error) {
	exist, param, err := d.ParamGetOne(ctx, &sysModel.SysParam{
		Key:    key,
		Status: 1,
	})
	if err != nil {
		return false, err
	}
	if !exist || param.Value == "" {
		return false, nil
	}
	if err = enum.ToObject(param.Value, out); err != nil {
		return false, err
	}
	return true, nil
}

func (d *Dao) ParamList(ctx context.Context, req *sysModel.SysParam, page *typ.PageReq) (int64, []*sysModel.SysParam, error) {
	arr := make([]*sysModel.SysParam, 0)
	sess := d.dao.Context(ctx)
	if req.Id > 0 {
		sess.And("id = ?", req.Id)
	}
	if req.Key != "" {
		sess.And("`key` = ?", req.Key)
	}
	if req.Status > 0 {
		sess.And("`status` = ?", req.Status)
	}
	if req.Name != "" {
		sess.And("`name` like ?", req.Name+"%")
	}
	if req.Typ > 0 {
		sess.And("typ = ?", req.Typ)
	}
	if page != nil {
		count, err := sess.Limit(page.LimitStart()).Desc("id").FindAndCount(&arr)
		return count, arr, errc.WithStack(err)
	}
	err := sess.Desc("id").Find(&arr)
	return int64(len(arr)), arr, errc.WithStack(err)
}
func (d *Dao) DicList(ctx context.Context, req *sysModel.SysDic, page *typ.PageReq) (int64, []*sysModel.SysDic, error) {
	arr := make([]*sysModel.SysDic, 0)
	sess := d.dao.Context(ctx)
	if req.Id > 0 {
		sess.And("id = ?", req.Id)
	}
	if req.Key != "" {
		sess.And("`key` = ?", req.Key)
	}
	if req.Status > 0 {
		sess.And("`status` = ?", req.Status)
	}
	if req.Value != "" {
		sess.And("`value` like ?", req.Value)
	}
	if page != nil {
		count, err := sess.Limit(page.LimitStart()).Desc("id").FindAndCount(&arr)
		return count, arr, errc.WithStack(err)
	}
	err := sess.Desc("id").Find(&arr)
	return int64(len(arr)), arr, errc.WithStack(err)
}

func (d *Dao) DicOne(ctx context.Context, req *sysModel.SysDic) (bool, *sysModel.SysDic, error) {
	arr := &sysModel.SysDic{}
	session := d.dao.Context(ctx)
	if req.Id > 0 {
		session.And("id = ?", req.Id)
	}
	if req.UniqueKey != "" {
		session.And("unique_key = ?", req.UniqueKey)
	}
	exist, err := session.Get(arr)
	return exist, arr, errc.WithStack(err)
}

func (d *Dao) AreaList(ctx context.Context, in *sysModel.SysArea) ([]*sysModel.SysArea, error) {
	arr := make([]*sysModel.SysArea, 0)
	sess := d.dao.Context(ctx)
	if in.Id > 0 {
		sess.And("id = ?", in.Id)
	}
	if in.ParentId >= 0 {
		sess.And("parent_id = ?", in.ParentId)
	}
	err := sess.Find(&arr)
	return arr, errc.WithStack(err)
}
func (d *Dao) SysOperateLogList(ctx context.Context, in *sysModel.SysOperateLog, page *typ.PageReq, req *typ.TimeStringReq) (int64, []*sysModel.SysOperateLog, error) {
	arr := make([]*sysModel.SysOperateLog, 0)
	sess := d.dao.Context(ctx)
	if in.Id > 0 {
		sess.And("id = ?", in.Id)
	}
	if in.Opt != "" {
		sess.And("opt = ?", in.Opt)
	}
	if in.ResponseStatus > 0 {
		sess.And("response_status = ?", in.ResponseStatus)
	}
	if req != nil {
		cond := req.FieldSQLCond("create_at")
		for _, s := range cond {
			sess.And(s)
		}
	}
	row, err := sess.OrderBy("id desc").Limit(page.LimitStart()).FindAndCount(&arr)
	return row, arr, errc.WithStack(err)
}

func (d *Dao) ClassifyList(ctx context.Context, req *sysModel.SysClassify, page *typ.PageReq) (int64, []*sysModel.SysClassify, error) {
	arr := make([]*sysModel.SysClassify, 0)
	if req.Code != "" {
		req.ParentId = -1
	}
	sess := d.dao.Context(ctx)
	sess.And("is_del = 0")
	if req.Id > 0 {
		sess.And("id = ?", req.Id)
	}
	if req.ParentId >= 0 {
		sess.And("parent_id = ?", req.ParentId)
	}
	if req.Status > 0 {
		sess.And("`status` = ?", req.Status)
	}
	if req.Name != "" {
		sess.And("`name` = ?", req.Name)
	}
	if req.Code != "" {
		sess.And("`code` != ? and `code` like ? ", req.Code, req.Code)
	}
	if page != nil {
		if page.Count {
			count, err := sess.Limit(page.LimitStart()).Desc("id").FindAndCount(&arr)
			return count, arr, errc.WithStack(err)
		}
		err := sess.Limit(page.LimitStart()).Desc("id").Find(&arr)
		return int64(len(arr)), arr, errc.WithStack(err)
	}
	err := sess.Desc("id").Find(&arr)
	return int64(len(arr)), arr, errc.WithStack(err)
}
func (d *Dao) ClassifyOne(ctx context.Context, req *sysModel.SysClassify) (bool, *sysModel.SysClassify, error) {
	rs := &sysModel.SysClassify{}
	sess := d.dao.Context(ctx)
	sess.And("is_del = 0")
	if req.Id > 0 {
		sess.And("id = ?", req.Id)
	}
	if req.Code != "" {
		sess.And("`code` = ?", req.Code)
	}
	if req.Status > 0 {
		sess.And("`status` = ?", req.Status)
	}
	exist, err := sess.Desc("id").Get(&rs)
	return exist, rs, errc.WithStack(err)
}
func (d *Dao) ClassifyInsert(ctx context.Context, in, parent *sysModel.SysClassify) error {
	if parent == nil {
		in.ParentId = 0
		if err := d.GetDao().TxInsert(nil, in); err != nil {
			return err
		}
		return nil
	}

	row, classify, err := d.ClassifyList(ctx, &sysModel.SysClassify{
		ParentId: parent.Id,
	}, &typ.PageReq{
		Page:  1,
		Size:  1,
		Count: false,
	})
	if err != nil {
		return err
	}
	if row > 0 {
		in.Code = parent.Code + ":" + fmt.Sprintf("%03d", classify[0].Id+1)
	} else {
		in.Code = parent.Code + ":001"
	}
	in.ParentId = parent.Id
	if err := d.GetDao().TxInsert(nil, in); err != nil {
		return err
	}
	return nil
}
